/*************************************************************************
    > File Name: drvled.c
    > Author: klmyt 
    > Created Time: 2025年02月08日 星期六 09时17分55秒
 ************************************************************************/

#include "drvled.h"

#define LED_ON	(0x1101)
#define LED_OFF (0x1102)

typedef struct devled{
	int gpio;
	int index;
	char *name;
}devled_t;

typedef struct ledinfo{
	int size;
	devled_t* pleds;
}ledinfo_t;

typedef struct led {
	int index;
	int stauts;
	char name[10];
}led_t;

static devled_t* leds;
static int kindex;


static int drvled_probe(struct platform_device* pdev) {

	//获取灯的硬件信息
	ledinfo_t* pledinfo;
	int size, i;
	pledinfo = pdev->dev.platform_data;

	size = pledinfo-> size;

	leds = pledinfo->pleds;

	for(i = 0; i < size; i++) {
		//申请GPIO资源
		gpio_request(leds[i].gpio, leds[i].name);
		//默认灭灯
		gpio_direction_output(leds[i].gpio, 1);
	}

	return 0;
};

static int drvled_remove(struct platform_device* pdev) {
	//获取灯的硬件信息
	ledinfo_t* pledinfo;
	int size, i;
	pledinfo = pdev->dev.platform_data;

	size = pledinfo-> size;

	leds = pledinfo->pleds;

	for(i = 0; i < size; i++) {	
		//默认灭灯
		gpio_set_value(leds[i].gpio, 1);
		//释放GPIO资源
		gpio_free(leds[i].gpio);
	}

	return 0;
};


static struct platform_driver pd = {
	.driver = {
		.name= "myled"
	},
	.probe = drvled_probe,
	.remove = drvled_remove
};

static struct file_operations fos = {
	.read = drvled_read,
	.unlocked_ioctl = drvled_ctrl
};

static struct miscdevice misc = {
	.name = "myled",
	.minor = MISC_DYNAMIC_MINOR,
	.fops = &fos
};

//初始化
int drvled_init(void){

	platform_driver_register(&pd);

	misc_register(&misc);

	return 0;
};


void drvled_exit(void){

	platform_driver_unregister(&pd);

	misc_deregister(&misc);

};

long drvled_ctrl(struct file* f, unsigned int cmd, unsigned long buf){

	kindex = *(int*)buf;

	if(cmd == LED_ON){//开灯
		gpio_set_value(leds[kindex].gpio, 0);
	}

	if(cmd == LED_OFF){//关灯
		gpio_set_value(leds[kindex].gpio, 1);
	}

	return 0;
};

ssize_t drvled_read(struct file* f, char __user* buf, size_t count, loff_t* poss){

	int cpy_rslt;
	int tempStauts;
	led_t led;
	tempStauts = gpio_get_value(leds[kindex].gpio);
	led.index = kindex;
	led.stauts = tempStauts;
	strcpy(led.name, leds[kindex].name);
	

	printk("\n");
	printk("%s: led.index = %d, led.stauts= %d\n", __func__, led.index, led.stauts);

	cpy_rslt = copy_to_user(buf, &led, sizeof(led));

	if(cpy_rslt) {
		printk("%s : copy to user error, %s # %s \n", __func__, __DATE__, __TIME__);	
		return -EFAULT;
	
	} 

	return count;
}

module_init(drvled_init);
module_exit(drvled_exit);
MODULE_LICENSE("GPL");



